<?php
/**
 * 验证码类
 * 修改自 http://www.oschina.net/code/snippet_106025_6280
 */
class captcha
{
	private static $_instance = null;
	private $width            = 96;
	private $height           = 27;
	private $im;

	/**
	 * 获取实体
	 */
	public static function getInstance()
	{
		if (null === self::$_instance)
		{
			self::$_instance = new self();
		}
		return self::$_instance;
	}

	/**
	 * 输出验证码图片图片
	 * @method create
	 * @param  [mixed]  $num [验证码字符串或者验证码个数]
	 * @return [string]       [验证码]
	 * @author NewFuture
	 */
	public static function create($num = null)
	{

		$instance = self::getInstance();

		if (is_string($num))
		{
			$code = $num;
		}
		elseif (is_int($num) && $num < 10)
		{
			$num  = $num ?: 4;
			$code = $instance->createCode($num);
		}
		else
		{
			$code = $instance->createCode(4);
		}

		//创建图片
		$instance->createImg();
		//设置干扰元素
		$instance->setDisturb();
		//设置验证码
		$instance->setCaptcha($code);
		//输出图片
		$instance->outputImg();

		return $code;
	}

	/**
	 * 设置宽度
	 */
	// public static function setWidth($width)
	// {
	// 	$instance = self::getInstance();
	// 	$instance->width = $width;
	// }

	/**
	 * 设置高度
	 */
	//    public static function setHeight($height)
	//    {
	//        $instance = self::getInstance();
	//        $instance->height = $height;
	//    }

	private function __construct()
	{
	}

	private function createImg()
	{
		$this->im = imagecreatetruecolor($this->width, $this->height);
		$bgColor  = imagecolorallocate($this->im, 255, 255, 255);
		imagefill($this->im, 0, 0, $bgColor);
	}

	private function setDisturb()
	{
		$area       = ($this->width * $this->height) / 20;
		$disturbNum = ($area > 250) ? 250 : $area;
		//加入点干扰
		for ($i = 0; $i < $disturbNum; $i++)
		{
			$color = imagecolorallocate($this->im, rand(0, 255), rand(0, 255), rand(0, 255));
			imagesetpixel($this->im, rand(1, $this->width - 2), rand(1, $this->height - 2), $color);
		}
		//加入弧线
		for ($i = 0; $i <= 5; $i++)
		{
			$color = imagecolorallocate($this->im, rand(128, 255), rand(125, 255), rand(100, 255));
			imagearc($this->im, rand(0, $this->width), rand(0, $this->height), rand(30, 300), rand(20, 200), 50, 30, $color);
		}
	}

	private function createCode($n)
	{
		$str  = '23456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKMNPQRSTUVWXYZ';
		$code = '';
		for ($i = 0; $i < $n; $i++)
		{
			$code .= $str[rand(0, strlen($str) - 1)];
		}
		return $code;
	}

	private function setCaptcha($code)
	{
		$n = strlen($code);
		for ($i = 0; $i < $n; $i++)
		{
			$color = imagecolorallocate($this->im, rand(5, 150), rand(10, 150), rand(28, 150));
			$size  = rand(floor($this->height / 5), floor($this->height / 3));
			$x     = floor($this->width / $n * ($i + 0.2));
			$y     = rand($this->height / 3.5, $this->height / 2.5);
			imagechar($this->im, $size, $x, $y, $code[$i], $color);
		}
	}

	private function outputImg()
	{
		if (imagetypes() & IMG_JPG)
		{
			header('Content-type:image/jpeg');
			imagejpeg($this->im);
		}
		elseif (imagetypes() & IMG_GIF)
		{
			header('Content-type: image/gif');
			imagegif($this->im);
		}
		else
		{
			header('Content-type: image/png');
			imagepng($this->im);
		}
	}

}